<?php
/**
 * This file is part of webman.
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the MIT-LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @author    walkor<walkor@workerman.net>
 * @copyright walkor<walkor@workerman.net>
 * @link      http://www.workerman.net/
 * @license   http://www.opensource.org/licenses/mit-license.php MIT License
 */

use bang\validate\ValidateException;
use support\Request;
use support\Response;
use support\view\Raw;
use support\bootstrap\Translation;
use think\Collection;
use Webman\App;
use Webman\Config;
use app\common\extra\Status;

define('BASE_PATH', realpath(__DIR__ . '/../'));

if(!function_exists('base_path')){
    /**
     * @return string
     */
    function base_path()
    {
        return BASE_PATH;
    }
}


if(!function_exists('app_path')){
    /**
     * @return string
     */
    function app_path()
    {
        return BASE_PATH . DIRECTORY_SEPARATOR . 'app';
    }
}


if(!function_exists('public_path')){
    /**
     * @return string
     */
    function public_path()
    {
        return BASE_PATH . DIRECTORY_SEPARATOR . 'public';
    }
}


if(!function_exists('config_path')){
    /**
     * @return string
     */
    function config_path(string $module = '')
    {
        if(!empty($module)){
            return BASE_PATH . DIRECTORY_SEPARATOR . 'app'. DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR .'config';
        }
        return BASE_PATH . DIRECTORY_SEPARATOR . 'config';
    }
}


if(!function_exists('runtime_path')){
    /**
     * @return string
     */
    function runtime_path()
    {
        return BASE_PATH . DIRECTORY_SEPARATOR . 'runtime';
    }
}


if(!function_exists('response')){
    /**
     * @param int $status
     * @param array $headers
     * @param string $body
     * @return Response
     */
    function response($body = '', $status = 200, $headers = array())
    {
        return new Response($status, $headers, $body);
    }
}


if(!function_exists('json')){
    /**
     * @param $data
     * @param int $options
     * @return Response
     */
    function json($data, $options = JSON_UNESCAPED_UNICODE)
    {
        return new Response(200, ['Content-Type' => 'application/json'], json_encode($data, $options));
    }
}


if(!function_exists('jsonError')){
    /**
     * @param $code
     * @param array $data
     * @param string $msg
     * @return Response
     */
    function jsonError($code = 502 , $data = [] , $msg = '' )
    {
        $res['msg'] = empty($msg) ? (Status::getReasonPhrase($code)) : '';
        $res['data'] = $data;
        return new Response($code , ['Content-Type' => 'application/json'] , json_encode($res, JSON_UNESCAPED_UNICODE));
    }
}


if(!function_exists('jsonSuccess')){
    /**
     * @param int $code
     * @param array $data
     * @param string $msg
     * @return Response
     */
    function jsonSuccess($code = 200 , $data = [] , $msg = '' )
    {
        $res['msg'] = empty($msg) ? (Status::getReasonPhrase($code)) : $msg;
        $res['code'] = $code;
        $res['data'] = $data;
        return new Response($code , ['Content-Type' => 'application/json'] , json_encode($res, JSON_UNESCAPED_UNICODE));
    }
}


if(!function_exists('xml')){
    /**
     * @param $xml
     * @return Response
     */
    function xml($xml)
    {
        if ($xml instanceof SimpleXMLElement) {
            $xml = $xml->asXML();
        }
        return new Response(200, ['Content-Type' => 'text/xml'], $xml);
    }
}


if(!function_exists('jsonp')){
    /**
     * @param $data
     * @param string $callback_name
     * @return Response
     */
    function jsonp($data, $callback_name = 'callback')
    {
        if (!is_scalar($data) && null !== $data) {
            $data = json_encode($data);
        }
        return new Response(200, [], "$callback_name($data)");
    }
}


if(!function_exists('redirect')){
    /**
     * @param $location
     * @param int $status
     * @param array $headers
     * @return Response
     */
    function redirect($location, $status = 302, $headers = [])
    {
        $response = new Response($status, ['Location' => $location]);
        if (!empty($headers)) {
            $response->withHeaders($headers);
        }
        return $response;
    }
}


if(!function_exists('view')){
    /**
     * @param $template
     * @param array $vars
     * @param null $app
     * @return string
     */
    function view($template, $vars = [], $app = null)
    {
        static $handler;
        if (null === $handler) {
            $handler = config('view.handler');
        }
        return new Response(200, [], $handler::render($template, $vars, $app));
    }
}


if(!function_exists('request')){
    /**
     * @return Request
     */
    function request()
    {
        return App::request();
    }
}


if(!function_exists('config')){
    /**
     * @param $key
     * @param null $default
     * @return mixed
     */
    function config($key = null, $default = null)
    {
        return Config::get($key, $default);
    }
}


if (!function_exists('env')) {
    /**
     * @param $key
     * @param null $default
     * @return array|bool|false|mixed|string
     */
    function env($key, $default = null)
    {
        $value = getenv($key);

        if ($value === false) {
            return $default;
        }

        switch (strtolower($value)) {
            case 'true':
            case '(true)':
                return true;
            case 'false':
            case '(false)':
                return false;
            case 'empty':
            case '(empty)':
                return '';
            case 'null':
            case '(null)':
                return null;
        }

        if (($valueLength = strlen($value)) > 1 && $value[0] === '"' && $value[$valueLength - 1] === '"') {
            return substr($value, 1, -1);
        }

        return $value;
    }
}

if(!function_exists('trans')){
    /**
     * @param null|string $id
     * @param array $parameters
     * @param string|null $domain
     * @param string|null $locale
     * @return string
     */
    function trans(string $id, array $parameters = [], string $domain = null, string $locale = null)
    {
        return Translation::trans($id, $parameters, $domain, $locale);
    }
}


if(!function_exists('locale')){
    /**
     * @param null|string $locale
     * @return string
     */
    function locale(string $locale)
    {
        if (!$locale) {
            return Translation::getLocale();
        }
        Translation::setLocale($locale);
    }
}


if(!function_exists('worker_bind')){
    /**
     * @param $worker
     * @param $class
     */
    function worker_bind($worker, $class) {
        $callback_map = [
            'onConnect',
            'onMessage',
            'onClose',
            'onError',
            'onBufferFull',
            'onBufferDrain',
            'onWorkerStop',
            'onWebSocketConnect'
        ];
        foreach ($callback_map as $name) {
            if (method_exists($class, $name)) {
                $worker->$name = [$class, $name];
            }
        }
        if (method_exists($class, 'onWorkerStart')) {
            call_user_func([$class, 'onWorkerStart'], $worker);
        }
    }
}


if(!function_exists('cpu_count')){
    /**
     * @return int
     */
    function cpu_count() {
        if (strtolower(PHP_OS) === 'darwin') {
            $count = shell_exec('sysctl -n machdep.cpu.core_count');
        } else {
            $count = shell_exec('nproc');
        }
        $count = (int)$count > 0 ? (int)$count : 4;
        return $count;
    }
}


if(!function_exists('dump')){
    /**
     * 浏览器友好的变量输出
     * @access public
     * @param  mixed         $var 变量
     * @param  boolean       $echo 是否输出 默认为true 如果为false 则返回输出字符串
     * @param  string        $label 标签 默认为空
     * @param  integer       $flags htmlspecialchars flags
     * @return void|string
     */
    function dump($var, $echo = true, $label = null, $flags = ENT_SUBSTITUTE){
        $label = (null === $label) ? '' : rtrim($label) . ':';
        if ($var instanceof \think\Model || $var instanceof \think\model\Collection) {
            $var = $var->toArray();
        }

        ob_start();
        var_dump($var);

        $output = ob_get_clean();
        $output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', $output);

        if (PHP_SAPI == 'cli') {
            $output = PHP_EOL . $label . $output . PHP_EOL;
        } else {
            if (!extension_loaded('xdebug')) {
                $output = htmlspecialchars($output, $flags);
            }
            $output = '<pre>' . $label . $output . '</pre>';
        }
        if ($echo) {
            echo($output);
            return;
        }
        return $output;
    }
}

if(!function_exists('imgUrl')){
    /**
     * 链接拼接域名
     * @param string $url
     * @return string
     */
    function imgUrl($url = "")
    {
        if(preg_match("/^(http:\/\/|https:\/\/).*$/",$url)){
            return $url;
        }
        return Config::get('api.img_url').$url;
    }
}

if(!function_exists('imgUrlByArray')){
    function imgUrlByArray(array $data , string $key = "image")
    {
        foreach ($data as &$v){
            $v[$key] = imgUrl($v[$key]);
        }
        return $data;
    }
}


if (!function_exists('collection')) {
    /**
     * 数组转换为数据集对象
     * @param array|Collection $resultSet 数据集数组
     * @return \think\model\Collection|\think\Collection
     */
    function collection($resultSet)
    {
        $item = current($resultSet);
        if ($item instanceof \think\Model) {
            return \think\model\Collection::make($resultSet);
        } else {
            return \think\Collection::make($resultSet);
        }
    }
}

if(!function_exists('createRandomString')){
    function createRandomString(int $minLength = 8 , int $maxLength = 12 , string $alphabet = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'):string
    {
        $valArray = [$minLength , $maxLength];
        $minLength = min($valArray);
        $maxLength = max($valArray);
        $length = $minLength == $maxLength ? $minLength : mt_rand( $minLength , $maxLength);
        // 重复字母表以防止生成长度溢出字母表长度
        if ($length >= strlen($alphabet)) {
            $rate = intval($length / strlen($alphabet)) + 1;
            $alphabet = str_repeat($alphabet, $rate);
        }
        $res = substr(str_shuffle($alphabet), 0, $length);
        unset($alphabet , $valArray , $minLength , $maxLength , $length , $rate);
        return $res;
    }
}


if(!function_exists('validate')){

    /**
     * 简单的验证公共方法
     * @param $className
     * @param array $data
     * @param string|null $scene
     * @return bool
     * @throws ValidateException
     */
    function validate($className , $data = [] ,  string $scene = null){
        if(class_exists($className)){
            /**
             * @param \bang\validate\Validate $validateObject
             */
            $validateObject = new $className;
            if(!empty($scene)){
                if(!$validateObject->scene($scene)->check($data)){
                    throw new ValidateException($validateObject->getError());
                }
            }else{
                if(!$validateObject->check($data)){
                    throw new ValidateException($validateObject->getError());
                }
            }
        }else{
            throw new ValidateException("Class " . $className . " not found");
        }
        return true;
    }
}